#include <png.h>
#include <iostream>

// build libpng from source: https://github.com/glennrp/libpng
int main()
{
    auto png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
    if (png_ptr == nullptr)
    {
        std::cerr << "Failed to png_create_write_struct" << std::endl;
        png_destroy_write_struct(&png_ptr, nullptr);
        return -1;
    }

    auto info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == nullptr)
    {
        std::cerr << "Failed to png_create_info_struct" << std::endl;
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return -1;
    }

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        std::cerr << "Failed to setjmp" << std::endl;
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return -1;
    }

    FILE *fp = fopen("test.png", "wb");
    png_init_io(png_ptr, fp);
    png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
    png_set_IHDR(png_ptr, info_ptr, 512, 512, 8, PNG_COLOR_TYPE_RGB,
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    png_set_packing(png_ptr);
    png_write_info(png_ptr, info_ptr);

    unsigned char row[512 * 3];
    for (int i = 0; i < 512; ++i)
    {
        for (int j = 0; j < 512; ++j)
        {
            row[3 * j + 0] = i % 256;
            row[3 * j + 1] = j % 256;
            row[3 * j + 2] = (i + j) % 256;
        }
        png_write_row(png_ptr, row);
    }

    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);
    return 0;
}